#pragma once
#include "DataTypes.h"
#include "VisualizationExporter.h"
#include <vector>

class OptimizerNSGA {
public:
    OptimizerNSGA(const std::vector<int>& initial_schedule, const Graph& graph,
        const CodeMap& code_map, const Caps& caps, const Params& initial_params,
        const Options& options, VisualizationExporter* viz_exporter = nullptr);

    std::vector<Individual> run();

private:
    std::vector<int> initial_schedule_;
    Graph graph_;
    CodeMap code_map_;
    Caps caps_;
    Params initial_params_;
    Options options_;

    std::vector<std::vector<bool>> is_ancestor_;
    std::optional<std::pair<double, double>> initial_scores_;
    VisualizationExporter* viz_exporter_;

    void precomputeAncestors();
    void nonDominatedSort(std::vector<Individual>& population) const;

    std::vector<int> mutateSchedule(std::vector<int> schedule) const;
    Params mutateParams(Params params) const;

    std::tuple<double, double, std::string, Params> evaluateCandidateThreeWays(
        const std::vector<int>& schedule, const Params& spill_params,
        const std::optional<std::pair<double, double>>& initial_scores);
};